﻿using System;
using System.Linq.Expressions;

namespace Alex.Library.Specifications
{
    /// <summary>
    /// Specification's Interface
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ISpecification<T>
    {
        /// <summary>
        /// get specification expression. this always used in query from sql.
        /// </summary>
        /// <returns></returns>
        Expression<Func<T, bool>> GetExpression();

        /// <summary>
        /// determine the specification is true or false. 
        /// </summary>
        /// <returns></returns>
        bool IsSatisfiedBy(T obj);

        /// <summary>
        /// get a specification when And other.
        /// </summary>
        /// <param name="other">any specification</param>
        /// <returns>AndSpecification</returns>
        ISpecification<T> And(ISpecification<T> other);

        /// <summary>
        /// get a specification when Or other.
        /// </summary>
        /// <param name="other">any specification</param>
        /// <returns>OrSpecification</returns>
        ISpecification<T> Or(ISpecification<T> other);

        /// <summary>
        /// get a specification when Not.
        /// </summary>        
        /// <returns>NotSpecification</returns>
        ISpecification<T> Not();

        /// <summary>
        /// get a specification when And not(other).
        /// </summary>
        /// <param name="other">any specification</param>
        /// <returns>AndNotSpecification</returns>
        ISpecification<T> AndNot(ISpecification<T> other);

        /// <summary>
        /// get a specification when Or not(other).
        /// </summary>
        /// <param name="other">any specification</param>
        /// <returns>OrNotSpecification</returns>
        ISpecification<T> OrNot(ISpecification<T> other);
    }
}
